home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
nan_news
/
toolkit
/
menuto.prg
< prev
next >
Wrap
Text File
|
1991-08-15
|
13KB
|
383 lines
/*
* File......: MENUTO.PRG
* Author....: Ted Means
* Date......: $Date: 15 Aug 1991 23:03:54 $
* Revision..: $Revision: 1.2 $
* Log file..: $Logfile: E:/nanfor/src/menuto.prv $
*
* This is an original work by Ted Means and is placed in the
* public domain.
*
* Modification history:
* ---------------------
*
* $Log: E:/nanfor/src/menuto.prv $
*
* Rev 1.2 15 Aug 1991 23:03:54 GLENN
* Forest Belt proofread/edited/cleaned up doc
*
* Rev 1.1 14 Jun 1991 19:52:16 GLENN
* Minor edit to file header
*
* Rev 1.0 01 Apr 1991 01:01:42 GLENN
* Nanforum Toolkit
*
*/
/* $DOC$
* $FUNCNAME$
* MENU TO
* $CATEGORY$
* Menus/Prompts
* $ONELINER$
* Execute light bar menu using prompts created with @...PROMPT
* $SYNTAX$
* #include "FTMENUTO.CH"
*
* MENU TO <var> [NOSNOW] [KEEP] [COLD]
* $ARGUMENTS$
* <var> is the name of the variable to assign the result of the
* menu selection.
*
* ^bNOSNOW^b implements snow-suppression on CGA monitors. If not
* specified, no snow-suppression will occur. This option is only
* meaningful for CGA displays.
*
* ^bKEEP^b causes the prompt list to be retained after the menu
* has been executed, allowing the menu to be executed multiple
* times without redefining the prompts. If not specified, the
* prompts will be destroyed once the menu has executed.
*
* ^bCOLD^b suppresses automatic menu termination when a prompt's
* hotkey is pressed. If this clause is present, pressing
* a prompt's hotkey will move the highlight to the proper menu
* selection but will not terminate the menu. If not present,
* pressing a hot key will terminate the menu, as it does in the
* standard Clipper MENU TO command.
* $DESCRIPTION$
* This enhanced version of MENU TO requires the inclusion of
* the header file FTMENUTO.CH in any source file that uses it.
* It is compatible with, and may be used in place of, the standard
* Clipper MENU TO command.
*
* This command is very similar to the Clipper version. The
* main differences are that you have more control over hotkey
* operation, and you can keep the prompts alive after the menu
* has executed, if you so desire. Please be aware that this
* function does not qualify as a "wait state" and so do not
* expect any wait state-associated activity to occur.
* Nevertheless, I have included support for any SET KEY
* redirections through the magic of code blocks. A loop is
* used to check to every possible INKEY() value to see if it
* has been redirected. This is necessary because Clipper
* provides no way to check SET KEY status. If you're
* interested in improving performance, alter the source code
* to receive an array of keys that have been redirected, and
* remove the previously mentioned loop. Using the loop does
* make the routine a bit more generic, so it's a trade-off.
* Your call, do as you see fit.
*
* Note that this command can also be called using function-style
* syntax. See the entry for FT_MENUTO() for further details.
*
* Also note that this command calls an internal routine called
* __FTMENUTO(). __FTMENUTO() was written in assembler. Check
* the file TMENU.ASM if you're interested in seeing the
* assembler source code.
*
* Header file: FTMENUTO.CH
* $EXAMPLES$
* #include "FTMENUTO.CH" // NECESSARY!
* // Simple command
* MENU TO memvar
*
* // Implement snow-checking for CGA
* MENU TO memvar NOSNOW
*
* // Keep the prompts alive when finished
* MENU TO memvar KEEP
*
* // Use "cold" hotkeys
* MENU TO memvar COLD
* $INCLUDE$
* FTMENUTO.CH
* $SEEALSO$
* "@...PROMPT" FT_MENUTO() FT_PROMPT()
* $END$
*/
/* $DOC$
* $FUNCNAME$
* FT_MENUTO()
* $CATEGORY$
* Menus/Prompts
* $ONELINER$
* Execute light bar menu using prompts created with FT_PROMPT()
* $SYNTAX$
* FT_MENUTO( <bVarNameBlock>, <cVarName>, ;
* [ <lNoSnow> ], [ <lKeep> ], [ <lCold> ]) -> nChoice
* $ARGUMENTS$
* <bVarNameBlock> is a "get-set" code block which allows the
* retrieval and assignment of the variable which will receive
* the return value. Its initial value is used to determine the
* initial active prompt.
*
* The code block must be in the form:
*
* {|_1| IIF( _1 == NIL, <var>, <var> := _1 ) }
*
* For example, if the variable to receive the return value is
* named "nChoice", the code block would look like:
*
* {|_1| IIF( _1 == NIL, nChoice, nChoice := _1 ) }
*
* Although it is good practice to always declare your variables,
* the variable to receive the return value does not need to exist
* before calling FT_MENUTO(). If it does exist and is a numeric,
* its value will be used to determine the initial prompt. If it
* does not exist, the initial prompt will default to the first one.
*
* If you use this function by way of the MENU TO command along with
* the FTMENUTO.CH header file, this code block will automatically
* be created for you by the preprocessor.
*
* <cVarName> is the name of the memvar to which the menu
* choice is returned.
*
* <lNoSnow> is optional and specifies whether or not to
* implement snow-suppression on CGA monitors. The default is
* .F., meaning that no snow-suppression will occur. This
* option is only meaningful for CGA displays.
*
* <lKeep> is optional and indicates whether or not to destroy
* the prompt list once the menu has been executed. If .T.,
* then the prompts will be kept, allowing the menu to be
* executed multiple times without redefining the prompts. The
* default is .F., meaning the prompts will be destroyed once
* the menu has executed.
*
* <lCold> is optional and controls the operation of the
* hotkeys. If .T., then pressing a hotkey will not result in
* a menu selection. Instead, it merely changes the active
* prompt. This allows more than one prompt to have the same
* hotkey. The default is .F., meaning the hotkeys will
* function the same way they do in Clipper.
* $RETURNS$
* A numeric value representing the menu choice selected, or zero
* if the ESC key was used to exit the menu.
* $DESCRIPTION$
* This function is a replacement for Clipper's MENU TO
* command. In fact, you may wish to consult TMENU.CH, which
* contains a user-defined command that closely adheres to
* standard Clipper syntax and makes this function infinitely
* easier to use. I strongly recommend using the command
* version because it is complementary to the associated
* @...PROMPT command.
*
* This function is very similar to the Clipper version. The
* main differences are that you have more control over hotkey
* operation, and you can keep the prompts alive after the menu
* has executed, if you so desire. Please be aware that this
* function does not qualify as a "wait state" and so do not
* expect any wait state-associated activity to occur.
* Nevertheless, I have included support for any SET KEY
* redirections through the magic of code blocks. A loop is
* used to check to every possible INKEY() value to see if it
* has been redirected. This is necessary because Clipper
* provides no way to check SET KEY status. If you're
* interested in improving performance, alter the source code
* to receive an array of keys that have been redirected, and
* remove the previously mentioned loop. Using the loop does
* make the routine a bit more generic, so it's a trade-off.
* Your call, do as you see fit.
*
* Note that this function calls an internal routine called
* __FTMENUTO(). __FTMENUTO() was written in assembler. Check
* the file TMENU.ASM if you're interested in seeing the
* assembler source code.
*
* All the examples below use the command version. If you're
* interested in seeing the function version, compile the
* examples with the /P switch and then examine the resulting
* .PPO file.
* $EXAMPLES$
* #include "FTMENUTO.CH"
* // Simple command
* MENU TO memvar
*
* // Implement snow-checking for CGA
* MENU TO memvar NOSNOW
*
* // Keep the prompts alive when finished
* MENU TO memvar KEEP
*
* // Use "cold" hotkeys
* MENU TO memvar COLD
* $SEEALSO$
* FT_PROMPT()
* $END$
*/
#include "set.ch"
#include "inkey.ch"
#include "error.ch"
function FT_MenuTo( bReadvar, cReadVar, lNoSnow, lKeep, lCold )
local nFlags, aKey := {}, aKBlock := {}, bKBlock, i, nScanCode
local nActive, bErrorsys, oError
if valtype(bReadvar) != "B"
nActive := 1
else
bErrorsys := Errorblock( {|e| Break(e) } )
BEGIN SEQUENCE
nActive := Eval(bReadvar)
RECOVER USING oError
IF oError:gencode == EG_NOVAR
nActive := 1
ELSE
Eval(bErrorsys,oError)
ENDIF
END SEQUENCE
Errorblock(bErrorsys)
endif
if valtype(lNoSnow) != "L"
lNoSnow := .F.
endif
if valtype(lKeep) != "L"
lKeep := .F.
endif
if valtype(lCold) != "L"
lCold := .F.
endif
nFlags := iif(lNoSnow, 1, 0) ;
+ iif(lKeep, 2, 0) ;
+ iif(lCold, 4, 0) ;
+ iif(set(_SET_WRAP), 8, 0)
for i := -39 to 306
if (bKBLock := SetKey(i)) != NIL
_ftScanKey(i, aKey)
while len(aKBlock) < len(aKey)
AAdd(aKBlock, bKBlock)
end
endif
next
nScanCode := __ftMenuTo(nActive, nFlags, aKey)
nActive := int(nScanCode % (2 ^ 16))
nScanCode := int(nScanCode / (2 ^ 16))
while (i := aScan(aKey, nScanCode)) > 0
if valtype(bReadvar) == "B"
eval(bReadvar,nActive)
endif
eval(aKBlock[i], ProcName(1), ProcLine(1), Upper(cReadVar))
nFlags := iif(nFlags < 32, nFlags + 32, nFlags)
nScanCode := __ftMenuTo(nActive, nFlags, aKey)
nActive := int(nScanCode % (2 ^ 16))
nScanCode := int(nScanCode / (2 ^ 16))
end
return nActive
static function _ftScanKey(nInKey, aKey)
do case
case nInKey == K_DEL
AAdd(aKey, 83 * 256)
AAdd(aKey, 7)
case nInKey == K_INS
AAdd(aKey, 82 * 256)
AAdd(aKey, 22)
case nInKey == K_UP
AAdd(aKey, 72 * 256)
AAdd(aKey, 5)
case nInKey == K_DOWN
AAdd(aKey, 80 * 256)
AAdd(aKey, 24)
case nInKey == K_LEFT
AAdd(aKey, 75 * 256)
AAdd(aKey, 19)
case nInKey == K_RIGHT
AAdd(aKey, 77 * 256)
AAdd(aKey, 4)
case nInKey == K_HOME
AAdd(aKey, 71 * 256)
AAdd(aKey, 1)
case nInKey == K_END
AAdd(aKey, 79 * 256)
AAdd(aKey, 6)
case nInKey == K_PGUP
AAdd(aKey, 73 * 256)
AAdd(aKey, 18)
case nInKey == K_PGDN
AAdd(aKey, 81 * 256)
AAdd(aKey, 3)
case nInKey == K_CTRL_LEFT
AAdd(aKey, 115 * 256)
AAdd(aKey, 26)
case nInKey == K_CTRL_RIGHT
AAdd(aKey, 116 * 256)
AAdd(aKey, 2)
case nInKey == K_CTRL_HOME
AAdd(aKey, 119 * 256)
AAdd(aKey, 29)
case nInKey == K_CTRL_END
AAdd(aKey, 117 * 256)
AAdd(aKey, 23)
case nInKey == K_CTRL_PGUP
AAdd(aKey, 132 * 256)
AAdd(aKey, 31)
case nInKey == K_CTRL_PGDN
AAdd(aKey, 118 * 256)
AAdd(aKey, 30)
case nInKey >= K_ALT_F10 .and. nInKey <= K_SH_F1
AAdd(aKey, (abs(nInKey) + 74) * 256)
case nInkey >= K_F10 .and. nInkey <= K_F2
AAdd(aKey, (abs(nInKey) + 59) * 256)
case nInkey == 28
AAdd(aKey, 59 * 256)
case (nInKey >= K_SH_TAB .and. nInKey <= K_ALT_P) .or. ;
(nInKey >= K_ALT_A .and. nInKey <= K_ALT_L) .or. ;
(nInKey >= K_ALT_Z .and. nInKey <= K_ALT_M)
AAdd(aKey, (nInKey - 256) * 256)
case (nInKey >= 0 .and. nInKey <= 255)
AAdd(aKey, nInKey)
endcase
return NIL